package cn.schoolwow.quickdao.module.database.dql.condition.flow.common;

import cn.schoolwow.quickdao.domain.QuickDAOConfig;
import cn.schoolwow.quickdao.domain.provider.DatabaseProvider;
import cn.schoolwow.quickdao.module.database.dql.condition.flow.get.GetFromConditionStatement;
import cn.schoolwow.quickdao.module.database.dql.parent.domain.QueryContext;
import cn.schoolwow.quickdao.module.database.dql.subCondition.domain.SubQueryOption;
import cn.schoolwow.quickflow.domain.FlowContext;
import cn.schoolwow.quickflow.flow.BusinessFlow;

import java.util.List;

public class SetSingleJoinTableStatementFlow implements BusinessFlow {
    @Override
    public void executeBusinessFlow(FlowContext flowContext) throws Exception {
        setJoinTableStatement(flowContext);
        appendJoinTableStatement(flowContext);
    }

    @Override
    public String name() {
        return "设置单个连表语句";
    }

    private void setJoinTableStatement(FlowContext flowContext){
        QuickDAOConfig quickDAOConfig = flowContext.checkInstanceData(QuickDAOConfig.class);
        SubQueryOption subQueryOption = (SubQueryOption) flowContext.checkData("subQueryOption");
        QueryContext queryContext = (QueryContext) flowContext.checkData("queryContext");

        //设置关联表信息
        if (null!=subQueryOption.subQueryTableOption.entity) {
            flowContext.putCurrentFlowData("joinTableStatement", quickDAOConfig.databaseContext.databaseProvider.escape(subQueryOption.subQueryTableOption.entity.tableName));
        } else if(null!=subQueryOption.subQueryTableOption.joinCondition){
            FlowContext fromConditionFlowContext = flowContext.getQuickFlow().startFlow(new GetFromConditionStatement())
                    .putTemporaryData("fromCondition", subQueryOption.subQueryTableOption.joinCondition)
                    .execute();
            List<Object> fromConditionParameters = (List<Object>) fromConditionFlowContext.getData("fromConditionParameters");
            queryContext.joinParameters.addAll(fromConditionParameters);

            flowContext.putCurrentFlowData("joinTableStatement", "(" + fromConditionFlowContext.checkData("fromConditionStatement") + ")");
        }else{
            throw new IllegalArgumentException("当前关联查询存在异常!");
        }
    }

    private void appendJoinTableStatement(FlowContext flowContext){
        SubQueryOption subQueryOption = (SubQueryOption) flowContext.checkData("subQueryOption");
        StringBuilder sqlBuilder = (StringBuilder) flowContext.checkData("sqlBuilder");
        String joinTableStatement = (String) flowContext.checkData("joinTableStatement");
        DatabaseProvider databaseProvider = flowContext.checkInstanceData(DatabaseProvider.class);

        //设置关联方式
        sqlBuilder.append(" " + subQueryOption.subQueryJoinTableOption.join + " ");
        sqlBuilder.append(joinTableStatement);
        sqlBuilder.append(" as " + databaseProvider.escape(subQueryOption.subQueryTableOption.tableAliasName));
        //设置关联表字段
        if (null != subQueryOption.subQueryJoinTableOption.primaryField && null != subQueryOption.subQueryJoinTableOption.joinTableField) {
            sqlBuilder.append(" on ");
            if (subQueryOption.subQueryJoinTableOption.parentSubQueryOption == null) {
                //子表关联主表
                sqlBuilder.append(databaseProvider.escape(subQueryOption.subQueryJoinTableOption.queryOption.queryTableOption.tableAliasName)
                        + "." +
                        databaseProvider.escape(subQueryOption.subQueryJoinTableOption.primaryField));
            } else {
                //子表关联子表
                sqlBuilder.append(databaseProvider.escape(subQueryOption.subQueryJoinTableOption.parentSubQueryOption.subQueryTableOption.tableAliasName)
                        + "."
                        + databaseProvider.escape(subQueryOption.subQueryJoinTableOption.primaryField));
            }
            sqlBuilder.append(" = " + databaseProvider.escape(subQueryOption.subQueryTableOption.tableAliasName) + "." + databaseProvider.escape(subQueryOption.subQueryJoinTableOption.joinTableField) + " ");

            flowContext.executeFlowList(new SetJoinTableOnAndStatementFlow());
        }
    }
}
